package com.matu.service;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

import com.matu.domain.StationVelo;
import com.matu.util.ToolBox;
import com.matu.util.Wgs84;

public class ServiceJCDecaux {

	private static String _uri = "https://api.jcdecaux.com/vls/v1/stations?contract=Toulouse";
	private static String _key = "&apiKey=57c6cf8a3bbcb8ff23944dd5697d326cb3ef7d3d";
	private URL url;
	private HttpURLConnection connection;
	
	
	/**
	 * Constructeur
	 */
	public ServiceJCDecaux() {
		
	}
	
	
	/**
	 * Permet de récupérer uniquement le nom de la station
	 * @param nomParse
	 * @return nom de la sation
	 */
	public String getNom(String nomParse) {
		String str[] = nomParse.split("-");
		String nom = "";
		
		// On supprime le numéro de la station
		for (int i=1; i<str.length; i++) {
			nom += str[i];
		}
		
		return nom;
	}
	
	
	/**
	 * Indique si une station est ouverte
	 * @param status
	 * @return vrai ou faux
	 */
	public boolean isOpen(String status) {
		return (status.equals("OPEN"));
	}
	
	
	/**
	 * Permet de récupérer toutes les stations de vélos de Toulouse au format Json
	 * @return Json
	 * @throws IOException
	 */
	public InputStream getServiceStationsToulouse() throws IOException {

		String requestUri= _uri + _key;
		url = new URL(requestUri);
		connection = (HttpURLConnection) url.openConnection();
		InputStream is = connection.getInputStream();

		return is;
	}
	
	
	/**
	 * Permet de récupérer le nom, le nombre de vélos disponibles,
	 * la latitude et la longitude de toutes les stations de Toulouse
	 * @return ArrayList d'un tableau composé d'un String et d'un Long et de 2 double
	 * @throws IOException 
	 * @throws ParseException 
	 */
	public ArrayList<StationVelo> getStations() throws IOException, ParseException {
		
		ArrayList<StationVelo> listStationVelosDisp = new ArrayList<StationVelo>();
		
		// On récupère la requête
		InputStream is = getServiceStationsToulouse();
		String resRequete = ToolBox.convertToString(is);
		
		// On parse
		JSONParser parser = new JSONParser();
		Object obj = parser.parse(resRequete);
		JSONArray lignes = (JSONArray) obj;
		
		@SuppressWarnings("unchecked")
		Iterator<JSONObject> it = lignes.iterator();
		while (it.hasNext())  {
			JSONObject velo = it.next();
			JSONObject position = (JSONObject) velo.get("position");
			
			String nomParse = (String) velo.get("name");
			String nom = getNom(nomParse);
			
			String status = (String) velo.get("status");
			boolean open = isOpen(status);
			
			Long nbPlacesVelo = (Long) velo.get("available_bike_stands");
			Long nbVelos = (Long) velo.get("available_bikes");
			double latitude = (Double) position.get("lat");
			double longitude = (Double) position.get("lng");
			
			listStationVelosDisp.add(
					new StationVelo(nom, open, nbVelos, nbPlacesVelo, latitude, longitude)
			);
		}
		
		return listStationVelosDisp;
	}
	
	
	/**
	 * Permet de trouver la station de vélo la plus proche d'une coordonnée
	 * @param latitude
	 * @param longitude
	 * @return la station la plus proche
	 */
	public StationVelo getClosestStation(double latitude, double longitude) {
		
		int iMin = -1;
		double coord[] = {0., 0.};
		double distanceMin = 100000000.;
		ArrayList<StationVelo> stations = null;
		
		try {
			
			stations = getStations();
			
			for (int i=0; i<stations.size(); i++) {
				coord[0] = stations.get(i).getLatitude();
				coord[1] = stations.get(i).getLongitude();
				
				double distance = Wgs84.distanceVolOiseauEntre2PointsSansPrécision
						(latitude, longitude, coord[0], coord[1]);
				
				if (distance < distanceMin) {
					iMin = i;
					distanceMin = distance;
				}
			}
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return stations.get(iMin);
	}
}
